#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#include "fifo.h"

Fifo newFifo(void)
{
  Fifo new;
  new = malloc(sizeof(Fifo_T));
  if (new == NULL)
    {
      fprintf(stderr, "newFifo() unable to allocate memory!\n");
    }
  new->head = 0;
  new->tail = 0;
  return new;
}

int isFifoEmpty(Fifo f)
{
  if (f->head == f->tail) return 1;
  else return 0;
}

void enqueue(Fifo f, FifoElement e)
{
  int tail;
  while (1)			/* blocking until queue'd */
    {
      tail = f->tail;
      if (incFifoPtr(tail) == f->head) continue; /* no more space */
      if (__sync_bool_compare_and_swap(&(f->tail), tail, incFifoPtr(tail)))
	{
	  f->queue[tail].element = e->element;
	  return;
	}
    }
}

void dequeue(Fifo f, FifoElement e)
{
  int head;
  while (1)
    {
      head = f->head;
      if (head == f->tail) continue; /* nothing to dequeue */
      if (__sync_bool_compare_and_swap(&(f->head), head, incFifoPtr(head)))
	{
	  e->element = f->queue[head].element;
	  return;
	}
    }
}

int nbdequeue(Fifo f, FifoElement e)
{
  int head;
  while (1)
    {
      head = f->head;
      if (head == f->tail) return 0; /* nothing to dequeue */
      if (__sync_bool_compare_and_swap(&(f->head), head, incFifoPtr(head)))
	{
	  e->element = f->queue[head].element;
	  return 1;
	}
    }
}

/* int main(int argc, char * argv[]) */
/* { */
/*   pthread_t threads[16]; */
/*   void *status; */
/*   int rc; */
/*   long t; */
/*   int i; */
/*   FifoElement_T d; */

/*   f = newFifo(); */
/*   for(t=0; t<atoi(argv[1]); t++) */
/*     { */
/*       printf("In main: creating thread %ld\n", t); */
/*       rc = pthread_create(&threads[t], NULL, tester, (void *)t); */
/*       if (rc) */
/* 	{ */
/* 	  printf("ERROR; return code from pthread_create() is %d\n", rc); */
/* 	  exit(-1); */
/* 	} */
/*     } */


/*   for(t=0; t<atoi(argv[1]); t++)  */
/*     { */
/*       rc = pthread_join(threads[t], &status); */
/*       if (rc)  */
/* 	{ */
/* 	  printf("ERROR; return code from pthread_join() is %d\n", rc); */
/* 	  exit(-1); */
/* 	} */
/*       printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status); */
/*     } */

/*   for (i = 0; i < atoi(argv[1]) * 10; i++) */
/*     { */
/*       dequeue(f, &d); */
/*       printf("%d\n", d.element); */
/*     } */

/*   pthread_exit(NULL); */
/* } */
